﻿using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using YaAppoint.RoslynCompiler;
using YaAppoint.Rules;

namespace YaAppoint.LocalCache
{
    [RemoteService(isEnabled: false)]
    public class LocalCacheAppService(IDynamicCompilerAppService compilerAppService) : ApplicationService, ILocalCacheAppService, ITransientDependency
    {
        private readonly IDynamicCompilerAppService _compilerAppService = compilerAppService;
       

        /// <summary>
        /// 缓存中获取/添加RuleFilter
        /// </summary>
        /// <param name="rule"></param>
        /// <returns></returns>
        public  RuleFilter GetOrAddRuleFilter(RuleDto rule)
        {
            var ruleFilter = new RuleFilter();
            ruleFilter.Order = rule.Order;
            ruleFilter.LogicType = rule.LogicType;
            ruleFilter.RuleId = rule.Id;
            ruleFilter.MD5 = _compilerAppService.GetCodeMD5(rule.Script!);// 计算MD5
            var cachedFilter =  LocalCache.Get(rule.Id);
            if (cachedFilter == null || cachedFilter.MD5 != ruleFilter.MD5)
            {
                if (cachedFilter != null) // 缓存中存在，卸载对应的 AssemblyLoadContext 
                {
                    cachedFilter.assemblyLoadContext.Unload();
                }
                DynamicAssemblyLoadContext assemblyLoadContext = null;
                var instance = _compilerAppService.CreateInstanceWithDI(rule.Script!, rule.TypeName, out assemblyLoadContext);
                if (instance == null)
                {
                    throw new Exception($"ID:{rule.Id}的规则，编译后未找到类型");
                }
                else if (instance is IRule ruleInstance)
                {
                    ruleFilter.Instance = ruleInstance;
                }
                else
                {
                    throw new Exception($"Id:{rule.Id}的规则，编译后实例类型不是IRule类型！");
                }
               
                ruleFilter.assemblyLoadContext = assemblyLoadContext;
                LocalCache.Set(rule.Id, ruleFilter);
            }
            else
            {
                ruleFilter = cachedFilter;
            }
            return ruleFilter;
        }
    }
}
